/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.sales.server;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author v
 */
public class HanServer extends HttpServlet {

    public HanServer() {
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        callMethodServer(req, resp);
    }

    private List<Map> toArray(String value) throws IOException {
        return new ObjectMapper().readValue(value, List.class);
    }

    private String toGson(Object value) throws IOException {
        Gson gson = new Gson();

        //convert java object to JSON format
        return gson.toJson(value);

    }

    private void callMethodServer(HttpServletRequest req, HttpServletResponse resp) {
        try {
            resp.setContentType("text/html");
//            PrintWriter out = resp.getWriter();
//            out.println("<html>");
//            out.println("Bem Vindo<h3>" + "Aldo" + " " + "Maciel" + "</h3>");
//            out.println("Bem Vindo<h2>" + "doPost" + "</h2>");
//            out.println("</html>");

            String className = req.getPathInfo().substring(1);
            className = className.substring(0, className.indexOf('/'));
            String methodName = req.getPathInfo().substring(req.getPathInfo().indexOf('/', 2) + 1, req.getPathInfo().length());

            Class cls = Class.forName("br.com.sales.hanserver.socket." + className + "Server");
            Object o = cls.newInstance();
            for (Method method : cls.getMethods()) {
                if (!methodName.equals(method.getName())) {
                    continue;
                }
                Class[] partypes = new Class[method.getParameterTypes().length];
                int i = 0;
                for (Object typeParameter : partypes) {
                    partypes[i] = method.getParameterTypes()[i];
                    i++;
                }
                Method meth = cls.getDeclaredMethod(methodName, partypes);
                Object[] arglist = new Object[method.getParameterTypes().length];
                String readLine = req.getReader().readLine();
                List parameterName = toArray(readLine);
                i = 0;
                for (Object valueParameter : parameterName) {
                    Object value = null;
                    Class t = partypes[i];
                    if (Integer.class.isAssignableFrom(t) || t.getName().equals("int")) {
                        value = ((Number) ((Map) valueParameter).get("value")).intValue();
                    } else if (Map.class.isAssignableFrom(t) || t.isInstance(Map.class)) {
                        value = ((Map) ((Map) valueParameter).get("value"));
                    } else if (Double.class.isAssignableFrom(t) || t.getName().equals("double")) {
                        value = ((Number) ((Map) valueParameter).get("value")).doubleValue();
                    } else if (String.class.isAssignableFrom(t)) {
                        value = ((String) ((Map) valueParameter).get("value"));
                    } else if (Date.class.isAssignableFrom(t)) {
                        value = ((Date) ((Map) valueParameter).get("value"));
                    } else if (Long.class.isAssignableFrom(t) || t.getName().equals("long")) {
                        value = ((Number) ((Map) valueParameter).get("value")).longValue();
                    } else if (Boolean.class.isAssignableFrom(t) || t.getName().equals("boolean")) {
                        value = ((Boolean) ((Map) valueParameter).get("value"));
                    } else {
                        value = ((Map) valueParameter).get("value");
                    }
                    arglist[i] = value;
                    i++;
                }
                Object invoke = meth.invoke(o, arglist);
                resp.getWriter().println(invoke == null ? null : toGson(invoke));
                System.out.println("invoke : " + invoke);
            }
        } catch (ClassNotFoundException | SecurityException | NoSuchMethodException | IOException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            System.err.println(e);
            Logger.getLogger(HanServer.class.getName()).log(Level.INFO, null, e);
        } catch (InstantiationException ex) {
            Logger.getLogger(HanServer.class.getName()).log(Level.INFO, null, ex);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        callMethodServer(req, resp);
    }
}
